<?php

declare(strict_types=1);

namespace App\Service;

use App\Common\Tools\DbTools;
use App\Constants\ErrorCode;
use App\Exception\BusinessException;
use App\Library\Common;
use App\Model\FlyShopCertificate;
use App\Model\FlyShopOpenTime;
use App\Model\ShopSendAddress;
use Hyperf\Database\Model\Builder;
use Hyperf\Database\Model\Model;
use Hyperf\DbConnection\Db;
use Hyperf\Di\Annotation\Inject;
use App\Model\FlyShop;

/**
 * 商家服务：保存基本信息、保存认证信息
 * Class FlyShopService
 * @package App\Service
 */
class FlyShopService extends BaseService
{

    const STYLE_TYPE_SHOP = 1;// 商城
    const STYLE_TYPE_FOOD = 2;// 餐饮美食

    const STATUS_WAIT_CHECK = 0;// 入驻待审核
    const STATUS_UP = 1;// 上架运营
    const STATUS_DOWN = 2;// 下架调整

    /**
     * @Inject()
     * @var AreainfoService
     */
    private $areainfo;


    /**
     * @Inject
     * @var FlyShopFansService
     */
    private $fans;

    /**
     * @Inject
     * @var FlyShopCertificateService
     */
    protected $shopCertService;

    /**
     * @Inject
     * @var FlyShopCertificateAttService
     */
    protected $shopCertAttService;

    /**
     * 获取adminId的商城模型
     * @param int $adminId
     * @param int $shopStyle
     * @return Builder|Model|object|null
     */
    public function getAdminShop(int $adminId, $shopStyle = self::STYLE_TYPE_SHOP)
    {
        return FlyShop::query(true)
            ->where('user_id', '=', $adminId)
            ->where('shop_style', '=', $shopStyle)
            ->first();
    }

    /**
     * 保存商家基本信息
     * @param array $params
     * @param bool $return_id
     * @return int
     */
    public function saveShopBaseInfo(array $params, bool $return_id = true): int
    {
        // food_switch(美食入驻申请凭证) 和 shop_type（云店、商城入驻凭证）
        $fields = ['shop_name', 'type', 'user_id', 'address_locate', 'address_info', 'link_name', 'phone', 'shop_type', 'food_switch', 'lat', 'lng'];

        $data = array_filter($params, function ($k) use ($fields) {
            if (!in_array($k, $fields)) {
                return false;
            } else {
                return true;
            }
        }, ARRAY_FILTER_USE_KEY);

        $model = $this->getModelInstance();
        foreach ($data as $field => $val) {
            $model->$field = $params[$field];
        }
        $model->create_time = time();
        $model->join_time = time();
        if (!$model->save()) {
            return 0;
        }

        // 保存商家默认地址
        Db::table('fly_shop_send_address')->updateOrInsert(
            ['shop_id' => $model->id, 'is_shop_addr' => 1],
            ['address_info' => $params['address_locate'] ?? "", 'link_name' => $params['link_name'], 'phone' => $params['phone'],
                'shop_id' => $model->id, 'lng' => $params['lng'], 'lat' => $params['lat']]
        );

        return $return_id ? $model->id : 1;
    }

    /**
     * 修改店铺基本信息
     * @param array $data
     * @param int $id
     * @return bool
     */
    public function updateShopBase(array $data, int $id): bool
    {
        if (empty($data) || empty($id)) {
            throw new BusinessException(ErrorCode::NORMAL_ERROR, '店铺不存在1');
        }
        $shop_instance = $this->getModelInstance()->find($id);
        if (empty($shop_instance)) {
            throw new BusinessException(ErrorCode::NORMAL_ERROR, '店铺不存在2');
        }

        $new_data = array_filter($data, function ($item_key) {
            if (!in_array($item_key, ['shop_type', 'food_switch'])) {
                return false;
            } else {
                return true;
            }
        }, ARRAY_FILTER_USE_KEY);

        foreach ($new_data as $k => $v) {
            $shop_instance->$k = $v;
        }
        if (!$shop_instance->save()) {
            return false;
        }
        return true;
    }


    /**
     * 商家完善信息（后台审核后同步）
     * @param array $params
     * @return bool
     */
    public function saveShopSupInfo(array $params): bool
    {
        // 保存认证基本信息 todo 集散地|行业
        $cert_id = $this->shopCertService->saveCert($params);
        if (!$cert_id) {
            return false;
        }
        $params['cert_id'] = $cert_id;
        $att_data = [];
        $att_type = ['license_id' => 2, 'id_front_id' => 3, 'id_back_id' => 4];
        $att_field = array_keys($att_type);
        foreach ($params as $k => $param) {
            if (in_array($k, $att_field)) {
                $att_data[] = [
                    'shop_id' => $params['shop_id'],
                    'fileinfo_id' => $k,
                    'cert_id' => $cert_id,
                    'type' => $att_type[$k]
                ];
            }
        }
        $params['cert_atts'] = $att_data;
        // 保存认证附件
        return $this->shopCertAttService->saveCertAtt($params);
    }

    /**
     * 获取我的店铺信息
     * @param int $user_id
     * @return array
     */
    public function getMyShop(int $user_id): array
    {
        if (empty($user_id)) {
            return [];
        }
        $myShop = $this->getModelInstance()
            ->where(['user_id' => $user_id])
            ->with(['with_industry', 'with_join_order'])
            ->first();
        if (empty($myShop)) {
            return [];
        }
        $return = $myShop->toArray();
        // 商家没有过入驻申请
        if (empty($return['with_join_order']) || !is_null($return['delete_time'])) {
            return [];
        }
        return $return;
    }

    /**
     * 获取店铺认证信息
     * @param int $shop_id
     * @return array
     */
    public function getCertInfo(int $shop_id): array
    {
        $finish_cert = make(FlyShopCertificate::class)
            ->with(['with_certs_file'])
            ->where(['shop_id' => $shop_id])
            ->first();
        return empty($finish_cert) ? [] : $finish_cert->toArray();
    }

    /**
     * 调整店铺行业保证金
     * @param int $shop_id
     * @param int $industry_id
     * @param $cash_price
     * @return bool
     */
    public function updateShopCash(int $shop_id, int $industry_id, $cash_price)
    {
        $instance = $this->getModelInstance()->find($shop_id);
        $instance->cash_industry = $industry_id;
        $instance->paid_cash = $cash_price;
        if (!$instance->save()) {
            return false;
        }
        return true;
    }

    /**
     * 检查店铺名
     * @param string $shop_name
     * @param bool $except_me
     * @param int $user_id
     * @return bool
     */
    public function checkShopName($shop_name = '', $except_me = false, int $user_id = 0): bool
    {
        return $this->getModelInstance()->checkShopName($shop_name, $except_me, $user_id);
    }

    /**
     * 获取店铺列表
     * @param array $id
     * @return array
     */
    public function getShopById(array $id): array
    {
        $id = array_unique($id);
        $instances = $this->getModelInstance()->findManyFromCache($id);
        if (empty($instances) || count($instances->toArray()) < count($id)) {
            $instances = $this->getModelInstance()->find($id);
        }
        return empty($instances) ? [] : $instances->toArray();
    }

    /**
     * @param int $shop_id
     * @param string $lng
     * @param string $lat
     * @return array
     */
    public function getShopInfo(int $shop_id, $lng = '', $lat = '')
    {
        $shop_info = FlyShop::query()
            ->where('id', $shop_id)
            ->with('with_industry')
            ->with('center_info')
            ->with('apply_info')
            ->with('certificate_att')
            ->with('reserved_set')
            ->with('meal_set')
            ->first();
        if ($shop_info) {
            $shop_info = $shop_info->toArray();
            if ($lat && $lng) {
                $shop_info['distance'] = DbTools::getPointDistance(floatval($lng), floatval($lat), floatval($shop_info['lng']), floatval($shop_info['lat']));
            } else {
                $shop_info['distance'] = 0;
            }
            $shop_info['shop_fans_num'] = $this->fans->getShopFans($shop_id);
            return $shop_info;
        } else {
            return [];
        }
    }

    /**
     * @param int $user_id
     * @param string $lng
     * @param string $lat
     * @return array
     */
    public function getShopInfoByUserId(int $user_id, $lng = '', $lat = '')
    {
        $shop_info = FlyShop::query()
            ->where('user_id', '=', $user_id)
            ->with('with_industry')
            ->with('center_info')
            ->with('apply_info')
            ->with('apply_food_info')
            ->with('certificate_att')
            ->first();
        if ($shop_info) {
            $shop_info = $shop_info->toArray();
            if ($lat && $lng) {
                $shop_info['distance'] = DbTools::getPointDistance(floatval($lng), floatval($lat), floatval($shop_info['lng']), floatval($shop_info['lat']));
            } else {
                $shop_info['distance'] = 0;
            }
            $shop_info['shop_fans_num'] = $this->fans->getShopFans(intval($shop_info['id']));
            return $shop_info;
        } else {
            return [];
        }
    }

    /**
     * 设置商家收货地址
     * @param $params
     * @return int
     */
    public function setShopAddress(array $params): int
    {
        if (!empty($params['id'])) {
            $my_shop_addr = make(ShopSendAddress::class)
                ->where('shop_id', '=', $params['shop_id'])
                ->find($params['id']);
            if (empty($my_shop_addr) || empty($my_shop_addr->toArray())) {
                throw new BusinessException(ErrorCode::NORMAL_ERROR, '参数错误');
            }
            if ($my_shop_addr->is_shop_addr == 1) {
                throw new BusinessException(ErrorCode::NORMAL_ERROR, '默认地址无法修改');
            }
        } else {
            $my_shop_addr = make(ShopSendAddress::class);
        }
        $data = array_filter($params, function ($k) {
            if (!in_array($k, ['street_id', 'address_info', 'name', 'phone', 'shop_id', 'lat', 'lng'])) {
                return false;
            } else {
                return true;
            }
        }, ARRAY_FILTER_USE_KEY);
        if (empty($data)) {
            return 0;
        }
        // 获取街道完整名称
        $street_arr = array_column($this->areainfo->getFullAddress($params['street_id']), 'name');
        $data['street_str'] = implode('', $street_arr);
        if (empty($data['lat']) || empty($data['lng'])) {
            $locate = Common::getAddressLocation($data['street_str'] . $data['address_info']);
            $data['lat'] = $locate['lat'] ?? 0;
            $data['lng'] = $locate['lng'] ?? 0;
        }
        foreach ($data as $field => $val) {
            $my_shop_addr->$field = $val;
        }
        if (!$my_shop_addr->save()) {
            throw new BusinessException(ErrorCode::NORMAL_ERROR, '保存失败');
        }
        return $street_arr->id;
    }

    /**
     * 获取店铺地址列表
     * @param int $shop_id
     * @return array
     */
    public function getShopAddress(int $shop_id): array
    {
        $list = make(ShopSendAddress::class)
            ->where(['shop_id' => $shop_id])
            ->whereNull('deleted_at')
            ->get();
        $return = empty($list) ? [] : $list->toArray();
        foreach ($return as &$addr) {
            $addr['street_arr'] = $this->areainfo->getFullAddress($addr['street_id']);
        }
        return $return;
    }

    /**
     * 删除商家地址
     * @param int $shop_id
     * @param int $id
     * @return bool
     */
    public function delShopAddress(int $shop_id, int $id): bool
    {
        $instance = make(ShopSendAddress::class)
            ->where(['shop_id' => $shop_id, 'id' => $id])
            ->update(['delete_time' => date('Y-m-d H:i:s', time())]);
        if (!$instance) {
            return false;
        }
        return true;
    }

    /**
     * 根据不同商铺类型获取 有效店铺信息
     * @param int $user_id
     * @param int $shop_style
     * @return array
     */
    public function getMyStyleShop(int $user_id, int $shop_style = self::STYLE_TYPE_SHOP): array
    {
        $myShop = $this->getModelInstance()->with(['with_join_dc', 'with_join_order'])
            ->whereHas('with_join_order', function ($with) use ($shop_style) {
                if ($shop_style == self::STYLE_TYPE_SHOP) {
                    $with->where('shop_style', '=', $shop_style);
                }
            })
            ->where(['user_id' => $user_id])
            ->where(function ($where) use ($shop_style) {
                if ($shop_style == self::STYLE_TYPE_SHOP) {
                    $where->where('shop_state', '=', self::STATUS_UP);
                } else {
                    $where->where('food_state', '=', self::STATUS_UP);
                }
            })
            ->first();
        return empty($myShop) ? [] : $myShop->toArray();
    }

    public function open_shop($start,$end)
    {
        return FlyShopOpenTime::query()
            ->where('start_time','<',$start)
            ->orWhere('end_time','>',$end)->groupBy('shop_id')->pluck('shop_id');
    }
}